﻿using System;
using System.Text;
using System.Ext.Xml;
using System.Xml;
using System.Reflection;

namespace mfXmlSerializer
{
    /// <summary>
    /// represents the serialization strategy for array-list
    /// </summary>
    public class mfMapArrayListElement : mfMapBaseElement
    {
        #region CTOR

        public mfMapArrayListElement(string name, MethodInfo addMethod, MethodInfo countMethod, MethodInfo getItemMethod)
            : base(name)
        {
            //init specialized properties
            AddMethod = addMethod;
            CountMethod = countMethod;
            GetItemMethod = getItemMethod;
        }

        #endregion

        #region Properties

        public MethodInfo AddMethod { get; set; }
        public MethodInfo CountMethod { get; set; }
        public MethodInfo GetItemMethod { get; set; }
        /// <summary>
        /// type object of this element
        /// </summary>
        public Type ItemType
        {
            get
            {
                if (GetItemMethod == null)
                {
                    throw new mfXmlException("no get_item-method for itemtype in " + this);
                }

                return GetItemMethod.ReturnType;
            }
        }

        #endregion

        #region Methods

        protected override void SerializeElement(XmlWriter xmlWriter, object source)
        {
            this.Check4ChildMap();
            //get child target object
            var childTarget = GetMethod.Invoke(source, null);
            if (childTarget == null)
            {
                return;
            }

            var count = Convert.ToInt32(CountMethod.Invoke(childTarget, null).ToString());

            for (int i = 0; i < count; i++)
            {
                var childObject = GetItemMethod.Invoke(childTarget, new object[] { i });

                //serialize child map
                ChildMap.SerializeMap(xmlWriter, childObject);
            }
        }

        protected override void DeserializeElement(XmlReader xmlReader, object target)
        {
            this.Check4ChildMap();

            string currentElement = string.Empty;

            var collectionTarget = GetMethod.Invoke(target, null);

            while (Name == xmlReader.Name)
            {
                var newChildItem = ItemType.CreateInstance(new Type[0], new object[0]);
                ChildMap.DeserializeMap(xmlReader, newChildItem);

                AddMethod.Invoke(collectionTarget, new object[] { newChildItem });

                xmlReader.Read();
            }

        }

        protected override void ExecuteSetElement(object target, string newValue)
        {
            throw new NotImplementedException("executeSet");
        }

        #endregion
    }
}
